import { CancelToken } from 'axios'

const pending = new Map()

let nId = 0

export const RegisterType = {
  GLOBAL: 'global',
  PAGE: 'page'
}

const getRequestKey = (config) => {
  const keyList = [config.requestRegisterType, config.method, config.url]
  if (config.requestId) {
    keyList.push(config.requestId)
  }
  return keyList.join('&')
}

export const registerPending = config => {
  const { requestRegisterType = RegisterType.PAGE, isIgnoreRequestRegister = false } = config
  if (isIgnoreRequestRegister) { return }
  config.requestRegisterType = requestRegisterType.includes('&') ? RegisterType.PAGE : requestRegisterType
  if (config.isUnique) {
    config.requestId = config.requestId || getRequestId()
  }
  const key = getRequestKey(config)
  if (pending.has(key)) {
    const cancel = pending.get(key)
    cancel(key)
    pending.delete(key)
  }
  config.cancelToken = config.cancelToken || new CancelToken(c => {
    pending.set(key, c)
  })
}

export const requestDone = config => {
  if (config.isIgnoreRequestRegister) { return }
  const key = getRequestKey(config)
  if (pending.has(key)) {
    pending.delete(key)
  }
}

export const clearPending = (registerType = RegisterType.PAGE) => {
  for (const [key, cancel] of pending) {
    const paramList = key.split('&')
    if (paramList.length > 0 && paramList[0] === registerType) {
      cancel(key)
      pending.delete(key)
    }
  }
}

export const clearAll = () => {
  for (const [key, cancel] of pending) {
    cancel(key)
  }
  pending.clear()
}

export const getRequestId = () => {
  return ++nId
}
